import time

from backend.app.crud.crud_goods import GoodsDao
from backend.app.services.db_common import DbPinecone
from backend.app.script.db_data_source import DataSourceByExcel


async def insert_by_file(path: str, start_page: int = 1, page_size=100):
    """
    根据文件路径插入excel数据
    :param path:
    :param start_page: 开始页码
    :param page_size: 页码大小
    :return:
    """
    # 初始化数据库
    index_name = "avl"
    db = DbPinecone(index_name=index_name)

    #  读取数据
    td = DataSourceByExcel()
    df = await td.read_excel(path)
    #  获取要插入的数据
    pages = td.get_pages(df.shape[0], page_size=page_size)
    #  分页插入数据
    err_texts, err_metadata = [], []
    for page in range(start_page, pages + 1):
        print(f"[insert_by_file] 总共{pages}页， 第{page} 开始获取当页数据.....")
        texts, metadata = await td.get_meta_data(df, page=page, page_size=page_size)
        print(f"[insert_by_file] 总共{pages}页， 第{page} 完成数据获取.....")
        is_success, result = await create_or_update_device(db, texts, metadata)
        if is_success:
            print(f"[insert_by_file] 总共{pages}页， 第{page} 页数据插入完成....")
        else:
            err_texts.extend(result["err_text"])
            err_metadata.extend(result["err_metadata"])
            print(f"[insert_by_file] 总共{pages}页， 第{page} 页数据插入失败....")
    print("页面大小：", page_size)
    print(err_texts)
    print(err_metadata)
    return


def insert_value(db, texts, metadata, is_reset=False):
    """插入重试"""
    is_success = True
    result = dict(vector_ids=[], err_text=[], err_metadata=[])
    if not (texts and metadata):
        return is_success, result

    try:
        result["vector_ids"] = db.batch_add(texts=texts, metadata=metadata)
    except Exception as e:
        print(e)
        if is_reset:
            is_success = False
            result["err_text"].extend(texts)
            result["err_metadata"].extend(metadata)
            return is_success, result

        time.sleep(1)
        pages = 3
        middle = int(len(texts) / pages)
        for i in range(pages):
            start = i * middle
            end = start + middle if i != pages - 1 else len(texts)
            is_success, res = insert_value(db, texts[start:end], metadata[start:end], is_reset=True)
            if is_success:
                result["vector_ids"].extend(res["vector_ids"])
            else:
                result["err_text"].extend(res["err_text"])
                result["err_metadata"].extend(res["err_metadata"])
            time.sleep(1)
    return is_success, result


async def create_or_update_device(db, texts, metadata):
    """插入重试"""
    is_success = True
    resp = dict(vector_ids=[], err_text=[], err_metadata=[])
    if not (texts and metadata):
        return is_success, resp

    vector_id_map = dict()

    update_list = []
    insert_text, insert_metadata = [], []
    for index, m in enumerate(metadata):
        # 查询设备是否添加过
        device_name = m.get("device_name", "")
        g_id = m.get("g_id")
        result = db.get_by_text(device_name, g_id=g_id)

        if result and result[0].get("vector_id"):
            update_list.append({"metadata": m, "id": result[0].get("vector_id"), "values": texts[index]})
            vector_id_map[int(g_id)] = result[0]["vector_id"]
        else:
            insert_text.append(texts[index])
            insert_metadata.append(m)

    print("----------------开始批量更新向量数据---------------- \n")
    try:
        db.batch_upsert(update_list)
    except Exception as e:
        print(e)
        is_success = False
        return is_success, resp

    print("----------------结束批量更新向量数据---------------- \n")
    print("----------------开始批量创建向量数据---------------- \n")
    try:
        vector_ids = db.batch_add(texts=insert_text, metadata=insert_metadata)
    except Exception as e:
        print(e)
        is_success = False
        resp["err_text"].extend(insert_text)
        resp["err_metadata"].extend(insert_metadata)
        return is_success, resp
    print("----------------结束批量创建向量数据---------------- \n")

    print("----------------开始更新设备向量ID---------------- \n")
    for index, vid in enumerate(vector_ids):
        gid = int(insert_metadata[index]["g_id"])
        vector_id_map[gid] = vid

    #  更新向量ID
    for goods_id, vector_id in vector_id_map.items():
        r = await GoodsDao.update_vector_id(goods_id, vector_id)

    print("----------------结束更新设备向量ID---------------- \n")

    return is_success, resp
